Essential steps for the modern software development process are the steps of testing and debugging software to ensure that the software will work and function as expected in its intended processing environment. These steps are usually implemented as methodical processes of finding and reducing the number of defects in the software program to make it behave as expected or intended. These are well-known to be cumbersome, time-consuming, and complicated tasks, and yet are in many cases performed manually with the end result very much reliant upon the individual level of skill of the programmer assigned to perform the testing and debugging tasks.
These tasks are often made much more difficult if the software program is tightly coupled to other devices or subsystems. This is because it is often difficult to determine and test the complex interactions between the software and the other subsystems and components in the overall system. Moreover, changes in one part of the system may cause unexpected results and errors to emerge in other parts the system.
Embedded software is a type of software (or firmware) that is designed to interact and interface in an integral way with a specific system or item of hardware. Designing and testing embedded software is considered to be very challenging for many designers since it normally require a multi-disciplinary approach to systems design that must take into account multifaceted effects throughout the different parts of the system. The programmer must consider many acute constraints for a successful design, such as energy consumption, memory space, criticality and safety considerations, and execution time. With many modern systems designs becoming more and more complex, these constraints are causing greater and greater difficulties for the design and testing process.
“Verification” is the term that is often used to refer to the process of determining a design meets requirements. In practice, verification is the process of identifying and removing as many functional bugs in the hardware and software as possible. The oldest form of verification is to build it, run it, and watch what happens.
Consider the problem of designing and verifying a System-on-Chip (SoC) involving both electronic hardware design and its associated embedded software design. The design verification process should be able to sufficiently test the SoC to ensure that it will work for its intended purpose. This is a very difficult challenge to ensure that the hardware and software work together at the SoC level. Hardware verification has advanced to the point where the verification of individual functional blocks in a design can be achieved with reasonable confidence using constrained random testbenches, code coverage, assertion coverage, and functional coverage.
However, significant problems exist for conventional techniques and tools when attempting to ensure that the software blocks work correctly when placed in the context of the SoC, since conventional SoC verification tools do not have the facility to adequately account for and test embedded software. Unfortunately, conventional approaches for SoC verification often result in many products that have subtle problems, most of which are caused by corner cases between the hardware and software. Many of today's consumer electronics are examples of this, where they contain advanced features constructed with complex hardware and software, but suffer from periodic lock-ups or require periodic reboots. The design of products produced using conventional verification techniques will have often failed to correct conditions where the hardware and software experience functional corner cases causing failures occur.